package com.yc.menu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yc.base.BaseServiceImpl;
import com.yc.constant.Constant;
import com.yc.enums.StatusEnum;
import com.yc.menu.entity.Menu;
import com.yc.menu.mapper.MenuMapper;
import com.yc.menu.service.IMenuService;
import com.yc.role.entity.Role;
import com.yc.role.entity.RoleMenuRelation;
import com.yc.role.mapper.RoleMenuRelationMapper;
import com.yc.role.service.IRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 后台菜单表 服务实现类
 * </p>
 *
 * @author bao
 * @since 2021-12-09
 */
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, Menu> implements IMenuService {

    private final IRoleService roleService;
    private final RoleMenuRelationMapper roleMenuRelationMapper;

    @Override
    public boolean create(Menu menu) {
        return save(menu);
    }

    @Override
    public boolean createBatch(List<Menu> menuList) {
        return saveBatch(menuList);
    }

    @Override
    public boolean delete(List<Long> ids) {
        return removeByIds(ids);
    }

    @Override
    public boolean update(Menu menu) {
        return updateById(menu);
    }

    @Override
    public Menu queryById(Long id) {
        return getById(id);
    }

    @Override
    public List<Menu> selectList() {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(Menu::getId);
        return list(wrapper);
    }

    @Override
    public IPage<Menu> selectPage(IPage<Menu> page) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(Menu::getId);
        return page(page, wrapper);
    }

    @Override
    public List<Menu> selectMenuPermission(long uid) {
        List<Menu> menuList = new ArrayList<>();
        List<Role> roleList = roleService.queryByUid(uid);
        boolean isAdministrator = roleList.stream().anyMatch(e -> e.getPermission().equals(Constant.administratorName));
        List<Long> roleIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(roleList) && !isAdministrator) {
            roleIds = roleList.stream().map(Role::getId).collect(Collectors.toList());
        }
        if (isAdministrator) {
            menuList = selectList();
            menuList = menuList.stream().filter(e -> e.getStatus() == StatusEnum.NORMAL).collect(Collectors.toList());
        } else if (!CollectionUtils.isEmpty(roleIds)) {
            List<RoleMenuRelation> sysRoleMenuRelationList = roleMenuRelationMapper.selectList(Wrappers.lambdaQuery(RoleMenuRelation.class).in(RoleMenuRelation::getRoleId, roleIds));
            Set<Long> menuIds = sysRoleMenuRelationList.stream().map(RoleMenuRelation::getMenuId).collect(Collectors.toSet());
            List<Menu> sysMenuList = list();
            List<Menu> childMenuList = sysMenuList.stream().filter(e -> menuIds.contains(e.getId())).toList();
            menuList.addAll(childMenuList);
            for (Menu menu : childMenuList) {
                List<Menu> parentMenuList = selectParentMenu(menu.getParentId(), sysMenuList);
                menuList.addAll(parentMenuList);
            }

        }
        menuList = menuList.stream().filter(distinctByKey(Menu::getId)).collect(Collectors.toList());
        return menuList;
    }

    private List<Menu> selectParentMenu(long parentId, List<Menu> sysMenuList) {
        List<Menu> outList = new ArrayList<>();
        outList.addAll(sysMenuList.stream().filter(e -> e.getId().equals(parentId))
                .peek(e -> outList.addAll(selectParentMenu(e.getParentId(), sysMenuList))).toList());
        return outList;
    }

}
